class Test::Unit::TestCase

  # Asserts that there is a numerical difference, of one by default, between
  # the output of (object).(method) before and after the block is called.
  #
  # Original idea: http://project.ioni.st/post/217#post-217
  # Reload addition: Ben Curtis
  # Duping addition: Mathew Toth
  #
  #     assert_difference(Publication, :count) do
  #       post :create, :publication => {...}
  #     end
  # 
  # For instances, you can use the reload flag to ensure a fresh record object:
  #
  #   assert_difference @item, :quantity, 1, true
  #     @cart.add_product!(@item.product.id)
  #   end
  # 
  def assert_difference(object, method = nil, difference = 1, reload = false)
    initial = (initial = object.send(method)).dup rescue initial
    yield
    object.reload if reload
    assert_equal initial + difference, object.send(method), "#{object}##{method}"
  end

  # Asserts that there is no numerical difference between the output of object.method
  # before and after the block.
  def assert_no_difference(object, method, reload = false, &block)
    assert_difference object, method, 0, reload, &block
  end

  # Asserts that the output of object.method is the same before and after the block.
  #
  #   assert_change @user, :title do
  #     @user.name = "Miss Bogart"
  #   end
  #
  def assert_change(object, method, reload = false)
    initial = (initial = object.send(method)).dup rescue initial
    yield
    object.reload if reload
    assert initial != object.send(method), "#{object}##{method}"
  end

  # Asserts that the output of object.method is the same before and after the block.
  def assert_no_change(object, method, reload = false)
    initial = (initial = object.send(method)).dup rescue initial
    yield
    object.reload if reload
    assert initial == object.send(method), "#{object}##{method}"
  end

end
